home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / progjour / 1989 / 05 / make.c < prev    next >
C/C++ Source or Header  |  1989-05-05  |  10KB  |  448 lines

  1. /*
  2.  *    Make.c        Un*x like program builder for MS-DOS
  3.  *
  4.  *    (C) Copyright 1985 Aspen Scientific
  5.  *
  6.  */
  7. #include    <stdio.h>
  8. #include    <sys/types.h>
  9. #include    <sys/stat.h>
  10. #include    <ctype.h>
  11.  
  12. #ifdef BUFSIZ
  13. # undef BUFSIZ
  14. # define BUFSIZ 2048
  15. #endif
  16.  
  17. #define    reg    register
  18. #define    INSTR    8
  19. #define    iscomment(c)    (c == '#')
  20. #define    nodisplay(c)    (c == '@')
  21. #define    MAXARG    64
  22. #define    strbck1(str)    strcpy(str, &str[1])    /* back up one char */
  23.  
  24. #ifndef UNIX
  25. #    include    <process.h>    /* defines P_WAIT for spawnvp() */
  26. #endif
  27.  
  28. /* compare command request to internal dos commands */
  29. static char    *idos[] = {
  30.     "break", "cd", "chdir", "cls", "copy", "ctty", "date", "del",
  31.     "dir", "echo", "erase", "exit", "exist", "if", "md", "mkdir",
  32.     "pause", "rd", "rem", "ren", "rename", "rmdir", "time", "type",
  33.     "ver", "verify", "vol",
  34.     (char *)0
  35. };
  36.  
  37. char    *m_argv[MAXARG];
  38. char    work[BUFSIZ], temp[BUFSIZ], buff[BUFSIZ];
  39.  
  40. typedef    struct deplist {
  41.     char    *depf;
  42. struct    deplist    *next;
  43. } DEP;
  44.  
  45. typedef    struct mklist {
  46.     DEP    *dep;
  47.     char    *targ;
  48.     int    echoi[INSTR];    /* should we echo the cmd ? */
  49.     char    *instr[INSTR];
  50. struct    mklist    *next;
  51. } MK;
  52.  
  53. MK    *mk = (MK *)0;        /* tree root */
  54. MK    *get_targ();
  55. #ifdef DEBUG
  56.     MK    *ddtmp;
  57.     DEP    *dddtmp;
  58. #endif
  59. FILE    *mk_fp, *script_fp;
  60.  
  61. char    *malloc();
  62. int    madeit = 0, mk_script = 0;        /* build shell script */
  63.  
  64. main(argc, argv)
  65. int    argc;
  66. char    **argv;
  67. {
  68.     reg    int    i;
  69.  
  70.     fprintf(stderr,"AS_Make v1.3 Copyright 1985,1989 Aspen Scientific ");
  71.     fprintf(stderr,"with mods for C++\n");
  72.     if((mk_fp = fopen("makefile", "r")) == (FILE *)0) {
  73.         fprintf(stderr,"\nMake: cannot open makefile.\n");
  74.         exit(2);
  75.     }
  76.     if(argc > 1 && argv[1][0] == '-') {
  77.         if(argv[1][1] != 'B' && argv[1][1] != 'b')
  78.             eusage();
  79.         if((script_fp = fopen("mk.bat","w"))==(FILE *)0) {
  80.             fprintf(stderr,"\nMake: cannot open MK.BAT.\n");
  81.             exit(2);
  82.         }
  83.         fprintf(script_fp,"echo off\ncls\n");
  84.         mk_script = 1;
  85.     }
  86.     set_mk();
  87. #ifdef DEBUG
  88.     for(ddtmp = mk; ddtmp; ddtmp = ddtmp->next)
  89.         for(dddtmp = ddtmp->dep; dddtmp; dddtmp = dddtmp->next)
  90.             printf("\ntarg->%s : dep->%s",
  91.                 ddtmp->targ,dddtmp->depf);
  92. #endif
  93.     fclose(mk_fp);
  94.     for(i = 0; i < MAXARG; m_argv[i++] = (char *)0);
  95.     if(mk == (MK *)0) {
  96.         fprintf(stderr,"\nMake: No arguments or description file.  Stop.");
  97.         exit(2);
  98.     }
  99.     if(argc < (2 + mk_script)) {
  100.         if(!mkit(mk->targ))
  101.             fprintf(stdout,"\n'%s' is up to date.", mk->targ);
  102.         else
  103.             ++madeit;
  104.     }
  105.     else {
  106.         for(i = (1+mk_script); i < argc; i++)
  107.             if(!mkit(argv[i]))
  108.                 fprintf(stdout,"\n'%s' is up to date.",argv[i]);
  109.             else
  110.                 ++madeit;
  111.     }
  112.     if(mk_script) {
  113.         fprintf(stdout,"\nMake: run command from MK.BAT");
  114.         fprintf(script_fp,"echo remove MK.BAT\ngoto end\n");
  115.         fprintf(script_fp,":stop\necho Make: errors detected.  Stop.\n:end\n");
  116.         fclose(script_fp);
  117.         if(!madeit)
  118.             unlink("mk.bat");
  119.     }
  120.     exit(0);
  121. }
  122. eusage()
  123. {
  124.     fprintf(stderr,"\nUsage: make [-B | -b] [target_name(s)]");
  125.     fprintf(stderr,"\n             -B : build Dos Batch script.\n");
  126.     exit(2);
  127. }
  128. set_mk()
  129. {
  130.     int    line;
  131.  
  132.     for(line = 1;;line++) {
  133.         if(!fgets(work, BUFSIZ, mk_fp))
  134.             break;
  135.         if(*work == '\n' || comment())
  136.             continue;
  137.         if(!scantarg(work, temp)) {
  138.             fprintf(stderr,"\nMake: bad target on line %d. Stop.\n", line);
  139.             exit(2);
  140.         }
  141.         fill_dep(temp, &work[strlen(temp)]);
  142.         fill_inst(&line);
  143.     }
  144. }
  145. scantarg(src, targ)
  146. char    *src, *targ;
  147. {
  148.     reg    int    i, j;
  149.  
  150.     for(i = 0, j = 0; src[i]; i++) {
  151.         if(isspace(src[i]))
  152.             continue;
  153.         if(src[i] == ':')
  154.             break;
  155.         targ[j++] = (isupper(src[i]) ? tolower(src[i]):src[i]);
  156.     }
  157.     targ[j] = '\0';
  158.     return(src[i]);
  159. }
  160. fill_dep(targ, dep)
  161. char    *targ, *dep;
  162. {
  163.     reg    int    i, j, k;
  164.     reg    MK    *tmp;
  165.     reg    DEP    *dtmp;
  166.  
  167.     if(mk == (MK *)0) {
  168.         if((mk = (MK *)malloc(sizeof(MK))) == (MK *)0)
  169.             mem_err();
  170.         tmp = mk;
  171.     }
  172.     else {
  173.         for(tmp = mk; ; tmp = tmp->next)
  174.             if(!tmp->next)
  175.                 break;
  176.         if((tmp->next = (MK *)malloc(sizeof(MK))) == (MK *)0)
  177.             mem_err();
  178.         tmp = tmp->next;
  179.     }
  180.     tmp->next = (MK *)0;
  181.     tmp->dep = (DEP *)0;
  182.     for(i = 0; i < INSTR; tmp->instr[i++] = (char *)0);
  183.     if((tmp->targ = malloc((strlen(targ)+1))) == (char *)0)
  184.         mem_err();
  185.     strcpy(tmp->targ, targ);
  186.     for(i = 0; dep[i]; i++)
  187.         if(!isspace(dep[i]) && dep[i] != ':')
  188.             break;
  189.     if(!dep[i])
  190.         return(0);    /* no dependancies */
  191.     for(;;) {
  192.         if(tmp->dep == (DEP *)0) {
  193.             if((tmp->dep = (DEP *)malloc(sizeof(DEP)))==(DEP *)0)
  194.                 mem_err();
  195.             dtmp = tmp->dep;
  196.         }
  197.         else {
  198.             if((dtmp->next = (DEP *)malloc(sizeof(DEP)))==(DEP *)0)
  199.                 mem_err();
  200.             dtmp = dtmp->next;
  201.         }
  202.         dtmp->depf = (char *)0;
  203.         dtmp->next = (DEP *)0;
  204.         for(k = 0, j = i; dep[j] && !isspace(dep[j]); j++)
  205.             buff[k++] = tolower(dep[j]);
  206.         buff[k] = '\0';
  207.         if((dtmp->depf = malloc((strlen(buff)+1)))==(char *)0)
  208.             mem_err();
  209.         strcpy(dtmp->depf, buff);
  210. #ifdef DEBUG
  211.         printf("\ndep arg=%s", buff);
  212. #endif
  213.         if(!dep[j])
  214.             break;
  215.         for(; ; j++) {
  216.             if(!dep[j])
  217.                 return;
  218.             if(isalnum(dep[j]))
  219.                 break;
  220.         }
  221.         i = j;
  222.     }
  223. }
  224. fill_inst(line)
  225. int    *line;
  226. {
  227.     reg    MK    *tmp;
  228.     reg    int    i, len;
  229.  
  230.     for(tmp = mk; ; tmp = tmp->next)
  231.         if(tmp->next == (MK *)0)
  232.             break;
  233.  
  234.     for(i = 0; i < INSTR; i++) {
  235.         if(!fgets(work, BUFSIZ, mk_fp))
  236.             break;
  237.         (*line)++;
  238.         if(*work == '\n')
  239.             break;
  240.         if(comment())
  241.             continue;
  242.         for(len = 0; work[len] && isspace(work[len]); len++);
  243.         if(!work[len] || work[len] == '\n')
  244.             continue;
  245.         if(work[((len = strlen(work) - 1))] == '\n')
  246.             work[len] = '\0';
  247.         if((tmp->instr[i] = malloc((len + 1))) == (char *)0)
  248.             mem_err();
  249.         strcpy(tmp->instr[i], work);
  250.     }
  251. }
  252. comment()
  253. {
  254.     int    i, flag;
  255.  
  256.     for(i = 0, flag = 0; work[i]; i++)
  257.         if(iscomment(work[i])) {
  258.             work[i] = '\0';
  259.             break;
  260.         }
  261.         else if(!isspace(work[i]))
  262.             ++flag;
  263.     return( (flag ? 0:1) );    /* only comment or only at end of line ? */
  264. }
  265. mem_err()
  266. {
  267.     fprintf(stderr,"\nMake: Out of memory.  Stop.\n");
  268.     exit(2);
  269. }
  270. mkit(targ)
  271. char    *targ;
  272. {
  273.     MK    *tmp;
  274.     DEP    *dtmp;
  275.  
  276.     int    i, j, len, made, go, display;
  277.  
  278.     made = go = 0;
  279.     if((tmp = get_targ(targ)) == (MK *)0) {
  280.         len = (strlen(targ) - 2);
  281.         if(strcmp(&targ[len], ".c") && strcmp(&targ[len], ".h")) {
  282.  
  283.             len -= 2;
  284.             if (strcmp(&targ[len], ".cpp") &&
  285.                 strcmp(&targ[len], ".hpp") &&
  286.                 strcmp(&targ[len], ".cxx") &&
  287.                 strcmp(&targ[len], ".hxx"))
  288.                 mk_err(targ);
  289.         }
  290.         return(0);
  291.     }
  292.     if(tmp->dep == (DEP *)0)
  293.         ++go;        /* no dependencies - do command */
  294.     else {
  295.         for(dtmp = tmp->dep ; ; ) {
  296. #ifdef DEBUG
  297.             printf("\ntarg->%s : arg->%s ",
  298.                 tmp->targ, dtmp->depf);
  299. #endif
  300.             mkit(dtmp->depf);
  301.             if(time_stamp(targ, dtmp->depf) != 0)
  302.                 ++go;
  303.             if(dtmp->next == (DEP *)0)
  304.                 break;
  305.             dtmp = dtmp->next;
  306.         }
  307.     }
  308.     if(go) {
  309.         for(i = 0; i < INSTR; i++)
  310.             if(tmp->instr[i]) {
  311.                 if(!bld_arg(tmp->instr[i]))
  312.                     continue;
  313.                 if(!nodisplay(m_argv[0][0]))
  314.                     display = 1;
  315.                 else {
  316.                     display = 0;
  317.                     strbck1(m_argv[0]);
  318.                 }
  319.                 for(j = 0; idos[j] && strcmp(idos[j],m_argv[0]); j++);
  320.                 if(mk_script) {
  321.                     strcpy(work, tmp->instr[i]);
  322.                     batch_it(work, display,
  323.                         (idos[j] != (char *)0));
  324.                     continue;
  325.                 }
  326.                 if(display)
  327.                     fprintf(stdout,"\n%s\n",tmp->instr[i]);
  328. #ifdef UNIX
  329.                 if(fork() != (-1)) {
  330.                     if(execvp(m_argv[0], m_argv) == (-1))
  331.                         instr_err();
  332.                 }
  333.                 else {
  334.                     wait(&go);
  335.                     if( (go &= 0xff00) )
  336.                         proc_err(go);
  337.                 }
  338. #else
  339.                 if(idos[j] != (char *)0) {
  340.                     strcpy(buff, tmp->instr[i]);
  341.                     zaplead(buff);
  342.                     if(system(buff) == (-1))
  343.                         instr_err();
  344.                 }
  345.                 else {
  346.                     go = spawnvp(P_WAIT, m_argv[0], m_argv);
  347.                     if(go == (-1))
  348.                         instr_err();
  349.                     if(go != 0)
  350.                         proc_err(go);
  351.                 }
  352. #endif
  353.             }
  354.         made++;
  355.     }
  356.     return(made);
  357. }
  358. batch_it(cmd, echo, isdos)
  359. char    *cmd;
  360. int    echo, isdos;
  361. {
  362.     if(echo)
  363.         fprintf(script_fp, "echo %s\n", cmd);
  364.     zaplead(cmd);
  365.     fprintf(script_fp, "%s\n", cmd);
  366.     /* cannot check for dos function exit code */
  367.     if(!isdos)
  368.         fprintf(script_fp, "if errorlevel == 1 goto stop\n");
  369. }
  370. MK    *get_targ(targ)
  371. char    *targ;
  372. {
  373.     reg    MK    *tmp;
  374.  
  375.     for(tmp = mk; tmp; tmp = tmp->next)
  376.         if(!strcmp(tmp->targ, targ))
  377.             return(tmp);
  378.     return(NULL);
  379. }
  380. time_stamp(targ, dep)
  381. char    *targ, *dep;
  382. {
  383.     struct    stat    t, d;
  384.  
  385.     if(stat(targ, &t) == (-1) || stat(dep, &d) == (-1))
  386.         return(1);        /* fake or non-existant target */
  387. /* ***
  388.     if(stat(dep, &d) == (-1)) {
  389.         fprintf(stderr,"\nMake: file '%s' does not exist.  Stop.\n",
  390.             dep);
  391. -        exit(2);
  392.     }
  393. *** */
  394.  
  395.     if(t.st_mtime < d.st_mtime)
  396.         return(1);
  397.     return(0);
  398. }
  399. bld_arg(instr)
  400. char    *instr;
  401. {
  402.     int    found;
  403.     reg    int    i;
  404.     reg    char    *p;
  405.  
  406.     strcpy(buff, instr);
  407.     for(i = 0; i < MAXARG; m_argv[i++] = (char *)0)
  408.         if(m_argv[i] == (char *)0)
  409.             break;
  410.     for(i = 0, p = buff; *p && i < MAXARG;)
  411.         if(isspace(*p))
  412.             for(; *p && isspace(*p); *p++ = '\0');
  413.         else {
  414.             ++found;
  415.             m_argv[i++] = p;
  416.             for(; *p && !isspace(*p); p++);
  417.         }
  418.     return(found);
  419. }
  420. zaplead(str)
  421. reg    char    *str;
  422. {
  423.     reg    int    i;
  424.  
  425.     for(i = 0; str[i]; i++)
  426.         if(!isspace(str[i]) && !nodisplay(str[i]))
  427.             break;
  428.     strcpy(str, &str[i]);
  429. }
  430. mk_err(targ)
  431. char    *targ;
  432. {
  433.     fprintf(stderr,"\nMake: don't know how to make '%s'\n",targ);
  434.     exit(2);
  435. }
  436. instr_err()
  437. {
  438.     fprintf(stderr,"\nMake: error bad instruction.  Stop.\n");
  439.     exit(2);
  440. }
  441. proc_err(err)
  442. int    err;
  443. {
  444.     fprintf(stderr,"\nMake: errors detected.\n***  Error code %d.\nStop.\n",
  445.         err);
  446.     exit(err);
  447. }
  448.